home *** CD-ROM | disk | FTP | other *** search
/ The Utilities Experience / The Utilities Experience - Volume 1.iso / software / misc / o-z / x-windows / mesa-amiwin / src / texture.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-11-30  |  47.0 KB  |  1,800 lines

  1. /* texture.c */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  1.2
  6.  * Copyright (C) 1995  Brian Paul  (brianp@ssec.wisc.edu)
  7.  *
  8.  * This library is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU Library General Public
  10.  * License as published by the Free Software Foundation; either
  11.  * version 2 of the License, or (at your option) any later version.
  12.  *
  13.  * This library is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * Library General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Library General Public
  19.  * License along with this library; if not, write to the Free
  20.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  */
  22.  
  23.  
  24. /*
  25. $Id: texture.c,v 1.22 1995/11/22 13:38:01 brianp Exp $
  26.  
  27. $Log: texture.c,v $
  28.  * Revision 1.22  1995/11/22  13:38:01  brianp
  29.  * removed texcoord clamping optimization
  30.  *
  31.  * Revision 1.21  1995/11/13  21:45:53  brianp
  32.  * fixed bug in texture border logic
  33.  * added F suffix to many constants
  34.  *
  35.  * Revision 1.20  1995/11/09  16:57:52  brianp
  36.  * fixed bugs in apply_texture for GL_BLEND per Johan Nouvel
  37.  *
  38.  * Revision 1.19  1995/11/03  17:39:30  brianp
  39.  * removed unused variable, added casts for C++ compilation
  40.  *
  41.  * Revision 1.18  1995/10/14  17:42:45  brianp
  42.  * compile glTexEnv, glTexParameter, and glTexGen into display lists
  43.  *
  44.  * Revision 1.17  1995/08/31  21:28:59  brianp
  45.  * new TexGenEnabled bitfield
  46.  * fixed a bug in spherical normal generation
  47.  *
  48.  * Revision 1.16  1995/07/24  20:35:40  brianp
  49.  * replaced memset() with MEMSET() and memcpy() with MEMCPY()
  50.  *
  51.  * Revision 1.15  1995/07/20  15:36:06  brianp
  52.  * added casts to PROD macro to suppress warnings with Sun's cc
  53.  *
  54.  * Revision 1.14  1995/06/12  15:43:06  brianp
  55.  * changed color arrays to GLubyte
  56.  *
  57.  * Revision 1.13  1995/05/30  15:41:23  brianp
  58.  * fixed GL_LUMINANCE bug in unpack_texture()
  59.  *
  60.  * Revision 1.12  1995/05/30  15:11:13  brianp
  61.  * added more error checking to glGetTexLevelParamater[fi]v()
  62.  * added glGetTexImage() stub
  63.  *
  64.  * Revision 1.11  1995/05/29  21:23:38  brianp
  65.  * added glGetTexEnv*(), glGetTexGen*(), glGetTex[Level]Parameter*() functions
  66.  *
  67.  * Revision 1.10  1995/05/22  21:02:41  brianp
  68.  * Release 1.2
  69.  *
  70.  * Revision 1.9  1995/05/18  14:46:51  brianp
  71.  * fixed texture DeleteFlag bug
  72.  *
  73.  * Revision 1.8  1995/05/16  14:09:44  brianp
  74.  * more data types supported by glTexImage1/2D()
  75.  *
  76.  * Revision 1.7  1995/05/15  16:09:41  brianp
  77.  * store textures as GLubytes instead of GLfloats
  78.  * implemented GL_MODULATE, GL_DECAL, GL_BLEND and GL_REPLACE_EXT modes
  79.  * save 1D and 2D textures in display lists
  80.  *
  81.  * Revision 1.6  1995/03/17  20:14:50  brianp
  82.  * small bug fixes
  83.  *
  84.  * Revision 1.5  1995/03/10  15:19:23  brianp
  85.  * added divide by zero check to gl_texgen
  86.  *
  87.  * Revision 1.4  1995/03/09  21:33:12  brianp
  88.  * removed #include stdio.h
  89.  *
  90.  * Revision 1.3  1995/03/04  19:29:44  brianp
  91.  * 1.1 beta revision
  92.  *
  93.  * Revision 1.2  1995/03/02  19:11:30  brianp
  94.  * modified gl_texgen and gl_texture_span_1d
  95.  *
  96.  * Revision 1.1  1995/02/24  14:28:31  brianp
  97.  * Initial revision
  98.  *
  99.  */
  100.  
  101.  
  102. #include <math.h>
  103. #include <stdio.h>
  104. #include <stdlib.h>
  105. #include <string.h>
  106. #include "context.h"
  107. #include "list.h"
  108. #include "macros.h"
  109. #include "pb.h"
  110.  
  111.  
  112. #ifndef NULL
  113. #  define NULL 0
  114. #endif
  115.  
  116.  
  117.  
  118. /**********************************************************************/
  119. /*                       Texture Environment                          */
  120. /**********************************************************************/
  121.  
  122.  
  123.  
  124. void gl_texenv( GLenum target, GLenum pname, const GLfloat *param )
  125. {
  126.    if (INSIDE_BEGIN_END) {
  127.       gl_error( GL_INVALID_OPERATION, "glTexEnv" );
  128.       return;
  129.    }
  130.  
  131.    if (target!=GL_TEXTURE_ENV) {
  132.       gl_error( GL_INVALID_ENUM, "glTexEnv(target)" );
  133.       return;
  134.    }
  135.  
  136.    if (pname==GL_TEXTURE_ENV_MODE) {
  137.       GLenum mode = (GLenum) (GLint) *param;
  138.       switch (mode) {
  139.      case GL_MODULATE:
  140.      case GL_BLEND:
  141.      case GL_DECAL:
  142.      case GL_REPLACE_EXT:
  143.         CC.Texture.EnvMode = mode;
  144.         break;
  145.      default:
  146.         gl_error( GL_INVALID_ENUM, "glTexEnv(param)" );
  147.         return;
  148.       }
  149.    }
  150.    else if (pname==GL_TEXTURE_ENV_COLOR) {
  151.       CC.Texture.EnvColor[0] = CLAMP( param[0], 0.0, 1.0 );
  152.       CC.Texture.EnvColor[1] = CLAMP( param[1], 0.0, 1.0 );
  153.       CC.Texture.EnvColor[2] = CLAMP( param[2], 0.0, 1.0 );
  154.       CC.Texture.EnvColor[3] = CLAMP( param[3], 0.0, 1.0 );
  155.    }
  156.    else {
  157.       gl_error( GL_INVALID_ENUM, "glTexEnv(pname)" );
  158.       return;
  159.    }
  160. }
  161.  
  162.  
  163.  
  164. void glTexEnvf( GLenum target, GLenum pname, GLfloat param )
  165. {
  166.    if (CC.CompileFlag) {
  167.       gl_save_texenv( target, pname, ¶m );
  168.    }
  169.    if (CC.ExecuteFlag) {
  170.       gl_texenv( target, pname, ¶m );
  171.    }
  172. }
  173.  
  174.  
  175.  
  176. void glTexEnvi( GLenum target, GLenum pname, GLint param )
  177. {
  178.    GLfloat p = (GLfloat) param;
  179.    if (CC.CompileFlag) {
  180.       gl_save_texenv( target, pname, &p );
  181.    }
  182.    if (CC.ExecuteFlag) {
  183.       gl_texenv( target, pname, &p );
  184.    }
  185. }
  186.  
  187.  
  188.  
  189. void glTexEnvfv( GLenum target, GLenum pname, const GLfloat *param )
  190. {
  191.    if (CC.CompileFlag) {
  192.       gl_save_texenv( target, pname, param );
  193.    }
  194.    if (CC.ExecuteFlag) {
  195.       gl_texenv( target, pname, param );
  196.    }
  197. }
  198.  
  199.  
  200.  
  201. void glTexEnviv( GLenum target, GLenum pname, const GLint *param )
  202. {
  203.    GLfloat p[4];
  204.    p[0] = INT_TO_FLOAT( param[0] );
  205.    p[1] = INT_TO_FLOAT( param[1] );
  206.    p[2] = INT_TO_FLOAT( param[2] );
  207.    p[3] = INT_TO_FLOAT( param[3] );
  208.    if (CC.CompileFlag) {
  209.       gl_save_texenv( target, pname, p );
  210.    }
  211.    if (CC.ExecuteFlag) {
  212.       gl_texenv( target, pname, p );
  213.    }
  214. }
  215.  
  216.  
  217.  
  218.  
  219. void glGetTexEnvfv( GLenum target, GLenum pname, GLfloat *params )
  220. {
  221.    if (target!=GL_TEXTURE_ENV) {
  222.       gl_error( GL_INVALID_ENUM, "glGetTexEnvfv(target)" );
  223.       return;
  224.    }
  225.    switch (pname) {
  226.       case GL_TEXTURE_ENV_MODE:
  227.          *params = (GLfloat) CC.Texture.EnvMode;
  228.      break;
  229.       case GL_TEXTURE_ENV_COLOR:
  230.      COPY_4V( params, CC.Texture.EnvColor );
  231.      break;
  232.       default:
  233.          gl_error( GL_INVALID_ENUM, "glGetTexEnvfv(pname)" );
  234.    }
  235. }
  236.  
  237.  
  238. void glGetTexEnviv( GLenum target, GLenum pname, GLint *params )
  239. {
  240.    if (target!=GL_TEXTURE_ENV) {
  241.       gl_error( GL_INVALID_ENUM, "glGetTexEnvfv(target)" );
  242.       return;
  243.    }
  244.    switch (pname) {
  245.       case GL_TEXTURE_ENV_MODE:
  246.          *params = (GLint) CC.Texture.EnvMode;
  247.      break;
  248.       case GL_TEXTURE_ENV_COLOR:
  249.      params[0] = FLOAT_TO_INT( CC.Texture.EnvColor[0] );
  250.      params[1] = FLOAT_TO_INT( CC.Texture.EnvColor[1] );
  251.      params[2] = FLOAT_TO_INT( CC.Texture.EnvColor[2] );
  252.      params[3] = FLOAT_TO_INT( CC.Texture.EnvColor[3] );
  253.      break;
  254.       default:
  255.          gl_error( GL_INVALID_ENUM, "glGetTexEnvfv(pname)" );
  256.    }
  257. }
  258.  
  259.  
  260.  
  261.  
  262. /**********************************************************************/
  263. /*                       Texture Parameters                           */
  264. /**********************************************************************/
  265.  
  266.  
  267. void gl_texparameter( GLenum target, GLenum pname, const GLfloat *params )
  268. {
  269.    GLenum eparam = (GLenum) (GLint) params[0];
  270.  
  271.    if (target==GL_TEXTURE_1D) {
  272.       switch (pname) {
  273.      case GL_TEXTURE_MIN_FILTER:
  274.         if (eparam==GL_NEAREST || eparam==GL_LINEAR
  275.         || eparam==GL_NEAREST_MIPMAP_NEAREST
  276.         || eparam==GL_LINEAR_MIPMAP_NEAREST
  277.         || eparam==GL_NEAREST_MIPMAP_LINEAR
  278.         || eparam==GL_LINEAR_MIPMAP_LINEAR) {
  279.            CC.Texture.MinFilter1D = eparam;
  280.         }
  281.         else {
  282.            gl_error( GL_INVALID_VALUE, "glTexParameter(param)" );
  283.         }
  284.         break;
  285.      case GL_TEXTURE_MAG_FILTER:
  286.         if (eparam==GL_NEAREST || eparam==GL_LINEAR) {
  287.            CC.Texture.MagFilter1D = eparam;
  288.         }
  289.         else {
  290.            gl_error( GL_INVALID_VALUE, "glTexParameter(param)" );
  291.         }
  292.         break;
  293.      case GL_TEXTURE_WRAP_S:
  294.         if (eparam==GL_CLAMP || eparam==GL_REPEAT) {
  295.            CC.Texture.WrapS1D = eparam;
  296.         }
  297.         else {
  298.            gl_error( GL_INVALID_VALUE, "glTexParameter(param)" );
  299.         }
  300.         break;
  301.      case GL_TEXTURE_WRAP_T:
  302.         if (eparam==GL_CLAMP || eparam==GL_REPEAT) {
  303.            CC.Texture.WrapT1D = eparam;
  304.         }
  305.         else {
  306.            gl_error( GL_INVALID_VALUE, "glTexParameter(param)" );
  307.         }
  308.         break;
  309.          case GL_TEXTURE_BORDER_COLOR:
  310.             CC.Texture.BorderColor[0] = CLAMP( params[0], 0.0, 1.0 );
  311.             CC.Texture.BorderColor[1] = CLAMP( params[1], 0.0, 1.0 );
  312.             CC.Texture.BorderColor[2] = CLAMP( params[2], 0.0, 1.0 );
  313.             CC.Texture.BorderColor[3] = CLAMP( params[3], 0.0, 1.0 );
  314.             break;
  315.      default:
  316.         gl_error( GL_INVALID_ENUM, "glTexParameter(pname)" );
  317.       }
  318.    }
  319.    else if (target==GL_TEXTURE_2D) {
  320.       switch (pname) {
  321.      case GL_TEXTURE_MIN_FILTER:
  322.         if (eparam==GL_NEAREST || eparam==GL_LINEAR
  323.         || eparam==GL_NEAREST_MIPMAP_NEAREST
  324.         || eparam==GL_LINEAR_MIPMAP_NEAREST
  325.         || eparam==GL_NEAREST_MIPMAP_LINEAR
  326.         || eparam==GL_LINEAR_MIPMAP_LINEAR) {
  327.            CC.Texture.MinFilter2D = eparam;
  328.         }
  329.         else {
  330.            gl_error( GL_INVALID_VALUE, "glTexParameter(param)" );
  331.         }
  332.         break;
  333.      case GL_TEXTURE_MAG_FILTER:
  334.         if (eparam==GL_NEAREST || eparam==GL_LINEAR) {
  335.            CC.Texture.MagFilter2D = eparam;
  336.         }
  337.         else {
  338.            gl_error( GL_INVALID_VALUE, "glTexParameter(param)" );
  339.         }
  340.         break;
  341.      case GL_TEXTURE_WRAP_S:
  342.         if (eparam==GL_CLAMP || eparam==GL_REPEAT) {
  343.            CC.Texture.WrapS2D = eparam;
  344.         }
  345.         else {
  346.            gl_error( GL_INVALID_VALUE, "glTexParameter(param)" );
  347.         }
  348.         break;
  349.      case GL_TEXTURE_WRAP_T:
  350.         if (eparam==GL_CLAMP || eparam==GL_REPEAT) {
  351.            CC.Texture.WrapT2D = eparam;
  352.         }
  353.         else {
  354.            gl_error( GL_INVALID_VALUE, "glTexParameter(param)" );
  355.         }
  356.         break;
  357.          case GL_TEXTURE_BORDER_COLOR:
  358.             CC.Texture.BorderColor[0] = CLAMP( params[0], 0.0, 1.0 );
  359.             CC.Texture.BorderColor[1] = CLAMP( params[1], 0.0, 1.0 );
  360.             CC.Texture.BorderColor[2] = CLAMP( params[2], 0.0, 1.0 );
  361.             CC.Texture.BorderColor[3] = CLAMP( params[3], 0.0, 1.0 );
  362.             break;
  363.      default:
  364.         gl_error( GL_INVALID_ENUM, "glTexParameter(pname)" );
  365.       }
  366.    }
  367.    else {
  368.       gl_error( GL_INVALID_ENUM, "glTexParameter(target)" );
  369.    }
  370. }
  371.  
  372.  
  373.  
  374. void glTexParameterf( GLenum target, GLenum pname, GLfloat param )
  375. {
  376.    if (CC.CompileFlag) {
  377.       gl_save_texparameter( target, pname, ¶m );
  378.    }
  379.    if (CC.ExecuteFlag) {
  380.       gl_texparameter( target, pname, ¶m );
  381.    }
  382. }
  383.  
  384.  
  385.  
  386. void glTexParameteri( GLenum target, GLenum pname, GLint param )
  387. {
  388.    GLfloat fparam = param;
  389.    if (CC.CompileFlag) {
  390.       gl_save_texparameter( target, pname, &fparam );
  391.    }
  392.    if (CC.ExecuteFlag) {
  393.       gl_texparameter( target, pname, &fparam );
  394.    }
  395. }
  396.  
  397.  
  398.  
  399. void glTexParameterfv( GLenum target, GLenum pname, const GLfloat *params )
  400. {
  401.    if (CC.CompileFlag) {
  402.       gl_save_texparameter( target, pname, params );
  403.    }
  404.    if (CC.ExecuteFlag) {
  405.       gl_texparameter( target, pname, params );
  406.    }
  407. }
  408.  
  409.  
  410.  
  411. void glTexParameteriv( GLenum target, GLenum pname, const GLint *params )
  412. {
  413.    GLfloat p[4];
  414.    if (pname==GL_TEXTURE_BORDER_COLOR) {
  415.       p[0] = INT_TO_FLOAT( params[0] );
  416.       p[1] = INT_TO_FLOAT( params[1] );
  417.       p[2] = INT_TO_FLOAT( params[2] );
  418.       p[3] = INT_TO_FLOAT( params[3] );
  419.    }
  420.    else {
  421.       p[0] = (GLfloat) params[0];
  422.       p[1] = (GLfloat) params[1];
  423.       p[2] = (GLfloat) params[2];
  424.       p[3] = (GLfloat) params[3];
  425.    }
  426.    if (CC.CompileFlag) {
  427.       gl_save_texparameter( target, pname, p );
  428.    }
  429.    if (CC.ExecuteFlag) {
  430.       gl_texparameter( target, pname, p );
  431.    }
  432. }
  433.  
  434.  
  435. void glGetTexLevelParameterfv( GLenum target, GLint level,
  436.                    GLenum pname, GLfloat *params )
  437. {
  438.    if (level<0 || level>=MAX_TEXTURE_LEVELS) {
  439.       gl_error( GL_INVALID_VALUE, "glGetTexLevelParameterfv" );
  440.       return;
  441.    }
  442.  
  443.    switch (target) {
  444.       case GL_TEXTURE_1D:
  445.          switch (pname) {
  446.         case GL_TEXTURE_WIDTH:
  447.            *params = (GLfloat) CC.TextureWidth1D[level];
  448.            break;
  449.         case GL_TEXTURE_COMPONENTS:
  450.            *params = (GLfloat) CC.TextureComponents1D[level];
  451.            break;
  452.         case GL_TEXTURE_BORDER:
  453.            *params = (GLfloat) CC.TextureBorder1D[level];
  454.            break;
  455.         default:
  456.            gl_error( GL_INVALID_ENUM, "glGetTexLevelParameterfv(pname)" );
  457.      }
  458.      break;
  459.       case GL_TEXTURE_2D:
  460.      switch (pname) {
  461.         case GL_TEXTURE_WIDTH:
  462.            *params = (GLfloat) CC.TextureWidth2D[level];
  463.            break;
  464.         case GL_TEXTURE_HEIGHT:
  465.            *params = (GLfloat) CC.TextureHeight2D[level];
  466.            break;
  467.         case GL_TEXTURE_COMPONENTS:
  468.            *params = (GLfloat) CC.TextureComponents2D[level];
  469.            break;
  470.         case GL_TEXTURE_BORDER:
  471.            *params = (GLfloat) CC.TextureBorder2D[level];
  472.            break;
  473.         default:
  474.            gl_error( GL_INVALID_ENUM, "glGetTexLevelParameterfv(pname)" );
  475.      }
  476.      break;
  477.      default:
  478.      gl_error( GL_INVALID_ENUM, "glGetTexLevelParameterfv(target)" );
  479.    }     
  480. }
  481.  
  482.  
  483. void glGetTexLevelParameteriv( GLenum target, GLint level,
  484.                    GLenum pname, GLint *params )
  485. {
  486.    if (level<0 || level>=MAX_TEXTURE_LEVELS) {
  487.       gl_error( GL_INVALID_VALUE, "glGetTexLevelParameteriv" );
  488.       return;
  489.    }
  490.  
  491.    switch (target) {
  492.       case GL_TEXTURE_1D:
  493.          switch (pname) {
  494.         case GL_TEXTURE_WIDTH:
  495.            *params = CC.TextureWidth1D[level];
  496.            break;
  497.         case GL_TEXTURE_COMPONENTS:
  498.            *params = CC.TextureComponents1D[level];
  499.            break;
  500.         case GL_TEXTURE_BORDER:
  501.            *params = CC.TextureBorder1D[level];
  502.            break;
  503.         default:
  504.            gl_error( GL_INVALID_ENUM, "glGetTexLevelParameteriv(pname)" );
  505.      }
  506.      break;
  507.       case GL_TEXTURE_2D:
  508.      switch (pname) {
  509.         case GL_TEXTURE_WIDTH:
  510.            *params = CC.TextureWidth2D[level];
  511.            break;
  512.         case GL_TEXTURE_HEIGHT:
  513.            *params = CC.TextureHeight2D[level];
  514.            break;
  515.         case GL_TEXTURE_COMPONENTS:
  516.            *params = CC.TextureComponents2D[level];
  517.            break;
  518.         case GL_TEXTURE_BORDER:
  519.            *params = CC.TextureBorder2D[level];
  520.            break;
  521.         default:
  522.            gl_error( GL_INVALID_ENUM, "glGetTexLevelParameteriv(pname)" );
  523.      }
  524.      break;
  525.      default:
  526.      gl_error( GL_INVALID_ENUM, "glGetTexLevelParameteriv(target)" );
  527.    }     
  528. }
  529.  
  530.  
  531.  
  532. void glGetTexParameterfv( GLenum target, GLenum pname, GLfloat *params )
  533. {
  534.    switch (target) {
  535.       case GL_TEXTURE_1D:
  536.          switch (pname) {
  537.         case GL_TEXTURE_MAG_FILTER:
  538.            *params = (GLfloat) CC.Texture.MagFilter1D;
  539.            break;
  540.         case GL_TEXTURE_MIN_FILTER:
  541.            *params = (GLfloat) CC.Texture.MinFilter1D;
  542.            break;
  543.         case GL_TEXTURE_WRAP_S:
  544.            *params = (GLfloat) CC.Texture.WrapS1D;
  545.            break;
  546.         case GL_TEXTURE_WRAP_T:
  547.            *params = (GLfloat) CC.Texture.WrapT1D;
  548.            break;
  549.         case GL_TEXTURE_BORDER_COLOR:
  550.            COPY_4V( params, CC.Texture.BorderColor );
  551.            break;
  552.         default:
  553.            gl_error( GL_INVALID_ENUM, "glGetTexParameterfv(pname)" );
  554.      }
  555.          break;
  556.       case GL_TEXTURE_2D:
  557.          switch (pname) {
  558.         case GL_TEXTURE_MAG_FILTER:
  559.            *params = (GLfloat) CC.Texture.MagFilter2D;
  560.            break;
  561.         case GL_TEXTURE_MIN_FILTER:
  562.            *params = (GLfloat) CC.Texture.MinFilter2D;
  563.            break;
  564.         case GL_TEXTURE_WRAP_S:
  565.            *params = (GLfloat) CC.Texture.WrapS2D;
  566.            break;
  567.         case GL_TEXTURE_WRAP_T:
  568.            *params = (GLfloat) CC.Texture.WrapT2D;
  569.            break;
  570.         case GL_TEXTURE_BORDER_COLOR:
  571.            COPY_4V( params, CC.Texture.BorderColor );
  572.            break;
  573.         default:
  574.            gl_error( GL_INVALID_ENUM, "glGetTexParameterfv(pname)" );
  575.      }
  576.      break;
  577.       default:
  578.          gl_error( GL_INVALID_ENUM, "glGetTexParameterfv(target)" );
  579.    }
  580. }
  581.  
  582.  
  583. void glGetTexParameteriv( GLenum target, GLenum pname, GLint *params )
  584. {
  585.    switch (target) {
  586.       case GL_TEXTURE_1D:
  587.          switch (pname) {
  588.         case GL_TEXTURE_MAG_FILTER:
  589.            *params = (GLint) CC.Texture.MagFilter1D;
  590.            break;
  591.         case GL_TEXTURE_MIN_FILTER:
  592.            *params = (GLint) CC.Texture.MinFilter1D;
  593.            break;
  594.         case GL_TEXTURE_WRAP_S:
  595.            *params = (GLint) CC.Texture.WrapS1D;
  596.            break;
  597.         case GL_TEXTURE_WRAP_T:
  598.            *params = (GLint) CC.Texture.WrapT1D;
  599.            break;
  600.         case GL_TEXTURE_BORDER_COLOR:
  601.            params[0] = FLOAT_TO_INT( CC.Texture.BorderColor[0] );
  602.            params[1] = FLOAT_TO_INT( CC.Texture.BorderColor[1] );
  603.            params[2] = FLOAT_TO_INT( CC.Texture.BorderColor[2] );
  604.            params[3] = FLOAT_TO_INT( CC.Texture.BorderColor[3] );
  605.            break;
  606.         default:
  607.            gl_error( GL_INVALID_ENUM, "glGetTexParameteriv(pname)" );
  608.      }
  609.          break;
  610.       case GL_TEXTURE_2D:
  611.          switch (pname) {
  612.         case GL_TEXTURE_MAG_FILTER:
  613.            *params = (GLint) CC.Texture.MagFilter2D;
  614.            break;
  615.         case GL_TEXTURE_MIN_FILTER:
  616.            *params = (GLint) CC.Texture.MinFilter2D;
  617.            break;
  618.         case GL_TEXTURE_WRAP_S:
  619.            *params = (GLint) CC.Texture.WrapS2D;
  620.            break;
  621.         case GL_TEXTURE_WRAP_T:
  622.            *params = (GLint) CC.Texture.WrapT2D;
  623.            break;
  624.         case GL_TEXTURE_BORDER_COLOR:
  625.            params[0] = FLOAT_TO_INT( CC.Texture.BorderColor[0] );
  626.            params[1] = FLOAT_TO_INT( CC.Texture.BorderColor[1] );
  627.            params[2] = FLOAT_TO_INT( CC.Texture.BorderColor[2] );
  628.            params[3] = FLOAT_TO_INT( CC.Texture.BorderColor[3] );
  629.            break;
  630.         default:
  631.            gl_error( GL_INVALID_ENUM, "glGetTexParameteriv(pname)" );
  632.      }
  633.      break;
  634.       default:
  635.          gl_error( GL_INVALID_ENUM, "glGetTexParameteriv(target)" );
  636.    }
  637. }
  638.  
  639.  
  640.  
  641.  
  642. /**********************************************************************/
  643. /*                    Texture Coord Generation                        */
  644. /**********************************************************************/
  645.  
  646.  
  647. void gl_texgen( GLenum coord, GLenum pname, const GLfloat *params )
  648. {
  649.    if (INSIDE_BEGIN_END) {
  650.       gl_error( GL_INVALID_OPERATION, "glTexGenfv" );
  651.       return;
  652.    }
  653.  
  654.    switch( coord ) {
  655.       case GL_S:
  656.          if (pname==GL_TEXTURE_GEN_MODE) {
  657.         GLenum mode = (GLenum) (GLint) *params;
  658.         if (mode==GL_OBJECT_LINEAR ||
  659.         mode==GL_EYE_LINEAR ||
  660.         mode==GL_SPHERE_MAP) {
  661.            CC.Texture.GenModeS = mode;
  662.         }
  663.         else {
  664.            gl_error( GL_INVALID_ENUM, "glTexGenfv(param)" );
  665.            return;
  666.         }
  667.      }
  668.      else if (pname==GL_OBJECT_PLANE) {
  669.         CC.Texture.ObjectPlaneS[0] = params[0];
  670.         CC.Texture.ObjectPlaneS[1] = params[1];
  671.         CC.Texture.ObjectPlaneS[2] = params[2];
  672.         CC.Texture.ObjectPlaneS[3] = params[3];
  673.      }
  674.      else if (pname==GL_EYE_PLANE) {
  675.         /* TODO:  xform plane by modelview??? */
  676.         CC.Texture.EyePlaneS[0] = params[0];
  677.         CC.Texture.EyePlaneS[1] = params[1];
  678.         CC.Texture.EyePlaneS[2] = params[2];
  679.         CC.Texture.EyePlaneS[3] = params[3];
  680.      }
  681.      else {
  682.         gl_error( GL_INVALID_ENUM, "glTexGenfv(pname)" );
  683.         return;
  684.      }
  685.      break;
  686.       case GL_T:
  687.          if (pname==GL_TEXTURE_GEN_MODE) {
  688.         GLenum mode = (GLenum) (GLint) *params;
  689.         if (mode==GL_OBJECT_LINEAR ||
  690.         mode==GL_EYE_LINEAR ||
  691.         mode==GL_SPHERE_MAP) {
  692.            CC.Texture.GenModeT = mode;
  693.         }
  694.         else {
  695.            gl_error( GL_INVALID_ENUM, "glTexGenfv(param)" );
  696.            return;
  697.         }
  698.      }
  699.      else if (pname==GL_OBJECT_PLANE) {
  700.         CC.Texture.ObjectPlaneT[0] = params[0];
  701.         CC.Texture.ObjectPlaneT[1] = params[1];
  702.         CC.Texture.ObjectPlaneT[2] = params[2];
  703.         CC.Texture.ObjectPlaneT[3] = params[3];
  704.      }
  705.      else if (pname==GL_EYE_PLANE) {
  706.         CC.Texture.EyePlaneT[0] = params[0];
  707.         CC.Texture.EyePlaneT[1] = params[1];
  708.         CC.Texture.EyePlaneT[2] = params[2];
  709.         CC.Texture.EyePlaneT[3] = params[3];
  710.      }
  711.      else {
  712.         gl_error( GL_INVALID_ENUM, "glTexGenfv(pname)" );
  713.         return;
  714.      }
  715.      break;
  716.       case GL_R:
  717.          if (pname==GL_TEXTURE_GEN_MODE) {
  718.         GLenum mode = (GLenum) (GLint) *params;
  719.         if (mode==GL_OBJECT_LINEAR ||
  720.         mode==GL_EYE_LINEAR) {
  721.            CC.Texture.GenModeR = mode;
  722.         }
  723.         else {
  724.            gl_error( GL_INVALID_ENUM, "glTexGenfv(param)" );
  725.            return;
  726.         }
  727.      }
  728.      else if (pname==GL_OBJECT_PLANE) {
  729.         CC.Texture.ObjectPlaneR[0] = params[0];
  730.         CC.Texture.ObjectPlaneR[1] = params[1];
  731.         CC.Texture.ObjectPlaneR[2] = params[2];
  732.         CC.Texture.ObjectPlaneR[3] = params[3];
  733.      }
  734.      else if (pname==GL_EYE_PLANE) {
  735.         CC.Texture.EyePlaneR[0] = params[0];
  736.         CC.Texture.EyePlaneR[1] = params[1];
  737.         CC.Texture.EyePlaneR[2] = params[2];
  738.         CC.Texture.EyePlaneR[3] = params[3];
  739.      }
  740.      else {
  741.         gl_error( GL_INVALID_ENUM, "glTexGenfv(pname)" );
  742.         return;
  743.      }
  744.      break;
  745.       case GL_Q:
  746.          if (pname==GL_TEXTURE_GEN_MODE) {
  747.         GLenum mode = (GLenum) (GLint) *params;
  748.         if (mode==GL_OBJECT_LINEAR ||
  749.         mode==GL_EYE_LINEAR) {
  750.            CC.Texture.GenModeQ = mode;
  751.         }
  752.         else {
  753.            gl_error( GL_INVALID_ENUM, "glTexGenfv(param)" );
  754.            return;
  755.         }
  756.      }
  757.      else if (pname==GL_OBJECT_PLANE) {
  758.         CC.Texture.ObjectPlaneQ[0] = params[0];
  759.         CC.Texture.ObjectPlaneQ[1] = params[1];
  760.         CC.Texture.ObjectPlaneQ[2] = params[2];
  761.         CC.Texture.ObjectPlaneQ[3] = params[3];
  762.      }
  763.      else if (pname==GL_EYE_PLANE) {
  764.         CC.Texture.EyePlaneQ[0] = params[0];
  765.         CC.Texture.EyePlaneQ[1] = params[1];
  766.         CC.Texture.EyePlaneQ[2] = params[2];
  767.         CC.Texture.EyePlaneQ[3] = params[3];
  768.      }
  769.      else {
  770.         gl_error( GL_INVALID_ENUM, "glTexGenfv(pname)" );
  771.         return;
  772.      }
  773.      break;
  774.       default:
  775.          gl_error( GL_INVALID_ENUM, "glTexGenfv(coord)" );
  776.      return;
  777.    }
  778.  
  779.    CC.NewState = GL_TRUE;
  780. }
  781.  
  782.  
  783.  
  784. void glTexGend( GLenum coord, GLenum pname, GLdouble param )
  785. {
  786.    GLfloat p = (GLfloat) param;
  787.    if (CC.CompileFlag) {
  788.       gl_save_texgen( coord, pname, &p );
  789.    }
  790.    if (CC.ExecuteFlag) {
  791.       gl_texgen( coord, pname, &p );
  792.    }
  793. }
  794.  
  795.  
  796. void glTexGenf( GLenum coord, GLenum pname, GLfloat param )
  797. {
  798.    if (CC.CompileFlag) {
  799.       gl_save_texgen( coord, pname, ¶m );
  800.    }
  801.    if (CC.ExecuteFlag) {
  802.       gl_texgen( coord, pname, ¶m );
  803.    }
  804. }
  805.  
  806.  
  807. void glTexGeni( GLenum coord, GLenum pname, GLint param )
  808. {
  809.    GLfloat p = (GLfloat) param;
  810.    if (CC.CompileFlag) {
  811.       gl_save_texgen( coord, pname, &p );
  812.    }
  813.    if (CC.ExecuteFlag) {
  814.       gl_texgen( coord, pname, &p );
  815.    }
  816. }
  817.  
  818.  
  819. void glTexGendv( GLenum coord, GLenum pname, const GLdouble *params )
  820. {
  821.    GLfloat p[4];
  822.    p[0] = params[0];
  823.    p[1] = params[1];
  824.    p[2] = params[2];
  825.    p[3] = params[3];
  826.    if (CC.CompileFlag) {
  827.       gl_save_texgen( coord, pname, p );
  828.    }
  829.    if (CC.ExecuteFlag) {
  830.       gl_texgen( coord, pname, p );
  831.    }
  832. }
  833.  
  834.  
  835. void glTexGeniv( GLenum coord, GLenum pname, const GLint *params )
  836. {
  837.    GLfloat p[4];
  838.    p[0] = params[0];
  839.    p[1] = params[1];
  840.    p[2] = params[2];
  841.    p[3] = params[3];
  842.    if (CC.CompileFlag) {
  843.       gl_save_texgen( coord, pname, p );
  844.    }
  845.    if (CC.ExecuteFlag) {
  846.       gl_texgen( coord, pname, p );
  847.    }
  848. }
  849.  
  850.  
  851. void glTexGenfv( GLenum coord, GLenum pname, const GLfloat *params )
  852. {
  853.    if (CC.CompileFlag) {
  854.       gl_save_texgen( coord, pname, params );
  855.    }
  856.    if (CC.ExecuteFlag) {
  857.       gl_texgen( coord, pname, params );
  858.    }
  859. }
  860.  
  861.  
  862. void glGetTexGendv( GLenum coord, GLenum pname, GLdouble *params )
  863. {
  864.    /* TODO */
  865. }
  866.  
  867. void glGetTexGenfv( GLenum coord, GLenum pname, GLfloat *params )
  868. {
  869.    /* TODO */
  870. }
  871.  
  872. void glGetTexGeniv( GLenum coord, GLenum pname, GLint *params )
  873. {
  874.    /* TODO */
  875. }
  876.  
  877.  
  878.  
  879. /*
  880.  * Perform automatic texture coordinate generation.
  881.  * Input:  obj - vertex in object coordinate system
  882.  *         eye - vertex in eye coordinate system
  883.  *         normal - normal vector in eye coordinate system
  884.  * Output:  texcoord - the resuling texture coordinate, if TexGen enabled.
  885.  */
  886. void gl_do_texgen( const GLfloat obj[4],
  887.                    const GLfloat eye[4],
  888.                    const GLfloat normal[3],
  889.                    GLfloat texcoord[4] )
  890. {
  891.    GLfloat u[3], two_nn, m, fx, fy, fz;
  892.  
  893.    if (CC.Texture.TexGenEnabled & S_BIT) {
  894.       switch( CC.Texture.GenModeS) {
  895.      case GL_OBJECT_LINEAR:
  896.             texcoord[0] = DOT4( obj, CC.Texture.ObjectPlaneS );
  897.         break;
  898.      case GL_EYE_LINEAR:
  899.         texcoord[0] = DOT4( eye, CC.Texture.EyePlaneS );
  900.         break;
  901.      case GL_SPHERE_MAP:
  902.             COPY_3V( u, eye );
  903.             NORMALIZE_3V( u );
  904.         two_nn = 2.0*DOT3(normal,normal);
  905.         fx = u[0] - two_nn * u[0];
  906.         fy = u[1] - two_nn * u[1];
  907.         fz = u[2] - two_nn * u[2];
  908.         m = 2.0 * sqrt( fx*fx + fy*fy + (fz+1.0)*(fz+1.0) );
  909.         if (m==0.0) {
  910.            texcoord[0] = 0.0;
  911.         }
  912.         else {
  913.            texcoord[0] = fx / m + 0.5;
  914.         }
  915.         break;
  916.       }
  917.    }
  918.  
  919.    if (CC.Texture.TexGenEnabled & T_BIT) {
  920.       switch( CC.Texture.GenModeT) {
  921.      case GL_OBJECT_LINEAR:
  922.         texcoord[1] = DOT4( obj, CC.Texture.ObjectPlaneT );
  923.         break;
  924.      case GL_EYE_LINEAR:
  925.         texcoord[1] = DOT4( eye, CC.Texture.EyePlaneT );
  926.         break;
  927.      case GL_SPHERE_MAP:
  928.         /* TODO: safe to assume that m and fy valid from above??? */
  929.         if (m==0.0) {
  930.            texcoord[1] = 0.0;
  931.         }
  932.         else {
  933.            texcoord[1] = fy / m + 0.5;
  934.         }
  935.         break;
  936.       }
  937.    }
  938.  
  939.    if (CC.Texture.TexGenEnabled & R_BIT) {
  940.       switch( CC.Texture.GenModeR) {
  941.      case GL_OBJECT_LINEAR:
  942.         texcoord[2] = DOT4( obj, CC.Texture.ObjectPlaneR );
  943.         break;
  944.      case GL_EYE_LINEAR:
  945.         texcoord[2] = DOT4( eye, CC.Texture.EyePlaneR );
  946.         break;
  947.       }
  948.    }
  949.  
  950.    if (CC.Texture.TexGenEnabled & Q_BIT) {
  951.       switch( CC.Texture.GenModeQ) {
  952.      case GL_OBJECT_LINEAR:
  953.         texcoord[3] = DOT4( obj, CC.Texture.ObjectPlaneQ );
  954.         break;
  955.      case GL_EYE_LINEAR:
  956.         texcoord[3] = DOT4( eye, CC.Texture.EyePlaneQ );
  957.         break;
  958.       }
  959.    }
  960. }
  961.  
  962.  
  963.  
  964. /**********************************************************************/
  965. /*                           Texture Image                            */
  966. /**********************************************************************/
  967.  
  968.  
  969. /*
  970.  * Convert the texture image given to glTexImage1D or glTexImage2D into
  971.  * an array of GLubytes.
  972.  * Return:  address of texture image or NULL if error.
  973.  */
  974. static GLubyte *unpack_texture( GLint components, GLsizei width, GLsizei height,
  975.                     GLenum format, GLenum type, const GLvoid *pixels )
  976. {
  977.    GLboolean rflag, gflag, bflag, aflag, lflag;
  978.    GLuint elements;
  979.    GLuint i, row;
  980.    GLubyte *texture, *texptr;
  981.    GLboolean scale_or_bias;
  982.  
  983.    scale_or_bias = CC.Pixel.RedScale  !=1.0F || CC.Pixel.RedBias  !=0.0F
  984.                 || CC.Pixel.GreenScale!=1.0F || CC.Pixel.GreenBias!=0.0F
  985.         || CC.Pixel.BlueScale !=1.0F || CC.Pixel.BlueBias !=0.0F
  986.         || CC.Pixel.AlphaScale!=1.0F || CC.Pixel.AlphaBias!=0.0F;
  987.  
  988.    switch (format) {
  989.       case GL_COLOR_INDEX:
  990.          elements = 1;
  991.      rflag = gflag = bflag = aflag = lflag = GL_FALSE;
  992.      break;
  993.       case GL_RED:
  994.      elements = 1;
  995.      rflag = GL_TRUE;
  996.      gflag = bflag = aflag = lflag = GL_FALSE;
  997.      break;
  998.       case GL_GREEN:
  999.      elements = 1;
  1000.      gflag = GL_TRUE;
  1001.      rflag = bflag = aflag = lflag = GL_FALSE;
  1002.      break;
  1003.       case GL_BLUE:
  1004.      elements = 1;
  1005.      bflag = GL_TRUE;
  1006.      rflag = gflag = aflag = lflag = GL_FALSE;
  1007.      break;
  1008.       case GL_ALPHA:
  1009.      elements = 1;
  1010.      aflag = GL_TRUE;
  1011.      rflag = gflag = bflag = lflag = GL_FALSE;
  1012.      break;
  1013.       case GL_RGB:
  1014.          elements = 3;
  1015.      rflag = gflag = bflag = GL_TRUE;
  1016.      aflag = lflag = GL_FALSE;
  1017.      break;
  1018.       case GL_RGBA:
  1019.          elements = 4;
  1020.      rflag = gflag = bflag = aflag = GL_TRUE;
  1021.      lflag = GL_FALSE;
  1022.      break;
  1023.       case GL_LUMINANCE:
  1024.          elements = 1;
  1025.      rflag = gflag = bflag = aflag = GL_FALSE;
  1026.      lflag = GL_TRUE;
  1027.      break;
  1028.       case GL_LUMINANCE_ALPHA:
  1029.          elements = 2;
  1030.      lflag = aflag = GL_TRUE;
  1031.      rflag = gflag = bflag = GL_FALSE;
  1032.          break;
  1033.       default:
  1034.          gl_error( GL_INVALID_ENUM, "glTexImage1/2D(format)" );
  1035.      return NULL;
  1036.    }
  1037.  
  1038.    /* Allocate texture memory */
  1039.    texture = (GLubyte *) malloc( width * height * components );
  1040.    if (!texture) {
  1041.       gl_error( GL_OUT_OF_MEMORY, "glTexImage1/2D" );
  1042.       return NULL;
  1043.    }
  1044.    texptr = texture;
  1045.  
  1046.    /* TODO: obey glPixelStore parameters! */
  1047.  
  1048.    /* Build texture map image row by row */
  1049.    for (row=0;row<height;row++) {
  1050.       if (type==GL_UNSIGNED_BYTE && format==GL_RGB && components==3
  1051.       && !scale_or_bias) {
  1052.      /*
  1053.       * A frequent and simple case
  1054.       */
  1055.      GLubyte *src = (GLubyte *) pixels + row * width * 3;
  1056.      MEMCPY( texptr, src, 3*width );
  1057.      texptr += 3*width;
  1058.       }
  1059.       else if (type==GL_UNSIGNED_BYTE && format==GL_RGBA && components==4
  1060.       && !scale_or_bias) {
  1061.      /*
  1062.       * Another frequent and simple case
  1063.       */
  1064.      GLubyte *src = (GLubyte *) pixels + row * width * 4;
  1065.      MEMCPY( texptr, src, 4*width );
  1066.      texptr += 4*width;
  1067.       }
  1068.       else {
  1069.      /*
  1070.       * General solution
  1071.       */
  1072.      GLfloat red[MAX_TEXTURE_SIZE], green[MAX_TEXTURE_SIZE];
  1073.      GLfloat blue[MAX_TEXTURE_SIZE], alpha[MAX_TEXTURE_SIZE];
  1074.  
  1075.      switch (type) {
  1076.         case GL_UNSIGNED_BYTE:
  1077.            {
  1078.           GLubyte *src = (GLubyte *) pixels + row * width * elements;
  1079.           for (i=0;i<width;i++) {
  1080.              if (lflag) {
  1081.             red[i] = green[i] = blue[i] = UBYTE_TO_FLOAT(*src++);
  1082.              }
  1083.              else {
  1084.             red[i]   = rflag ? UBYTE_TO_FLOAT(*src++) : 0.0F;
  1085.             green[i] = gflag ? UBYTE_TO_FLOAT(*src++) : 0.0F;
  1086.             blue[i]  = bflag ? UBYTE_TO_FLOAT(*src++) : 0.0F;
  1087.              }
  1088.              alpha[i] = aflag ? UBYTE_TO_FLOAT(*src++) : 1.0F;
  1089.           }
  1090.            }
  1091.            break;
  1092.         case GL_BYTE:
  1093.            {
  1094.           GLbyte *src = (GLbyte *) pixels + row * width * elements;
  1095.           for (i=0;i<width;i++) {
  1096.              if (lflag) {
  1097.             red[i] = green[i] = blue[i] = BYTE_TO_FLOAT(*src++);
  1098.              }
  1099.              else {
  1100.             red[i]   = rflag ? BYTE_TO_FLOAT(*src++) : 0.0F;
  1101.             green[i] = gflag ? BYTE_TO_FLOAT(*src++) : 0.0F;
  1102.             blue[i]  = bflag ? BYTE_TO_FLOAT(*src++) : 0.0F;
  1103.              }
  1104.              alpha[i] = aflag ? BYTE_TO_FLOAT(*src++) : 1.0F;
  1105.           }
  1106.            }
  1107.            break;
  1108.         case GL_UNSIGNED_SHORT:
  1109.            {
  1110.           GLushort *src = (GLushort *) pixels + row * width * elements;
  1111.           for (i=0;i<width;i++) {
  1112.              if (lflag) {
  1113.             red[i] = green[i] = blue[i] = USHORT_TO_FLOAT(*src++);
  1114.              }
  1115.              else {
  1116.             red[i]   = rflag ? USHORT_TO_FLOAT(*src++) : 0.0F;
  1117.             green[i] = gflag ? USHORT_TO_FLOAT(*src++) : 0.0F;
  1118.             blue[i]  = bflag ? USHORT_TO_FLOAT(*src++) : 0.0F;
  1119.              }
  1120.              alpha[i] = aflag ? USHORT_TO_FLOAT(*src++) : 1.0F;
  1121.           }
  1122.            }
  1123.            break;
  1124.         case GL_SHORT:
  1125.            {
  1126.           GLshort *src = (GLshort *) pixels + row * width * elements;
  1127.           for (i=0;i<width;i++) {
  1128.              if (lflag) {
  1129.             red[i] = green[i] = blue[i] = SHORT_TO_FLOAT(*src++);
  1130.              }
  1131.              else {
  1132.             red[i]   = rflag ? SHORT_TO_FLOAT(*src++) : 0.0F;
  1133.             green[i] = gflag ? SHORT_TO_FLOAT(*src++) : 0.0F;
  1134.             blue[i]  = bflag ? SHORT_TO_FLOAT(*src++) : 0.0F;
  1135.              }
  1136.              alpha[i] = aflag ? SHORT_TO_FLOAT(*src++) : 1.0F;
  1137.           }
  1138.            }
  1139.            break;
  1140.         /*TODO: implement rest of data types */
  1141.         case GL_FLOAT:
  1142.            {
  1143.           GLfloat *src = (GLfloat *) pixels + row * width * elements;
  1144.           for (i=0;i<width;i++) {
  1145.              if (lflag) {
  1146.             red[i] = green[i] = blue[i] = *src++;
  1147.              }
  1148.              else {
  1149.             red[i]   = rflag ? *src++ : 0.0F;
  1150.             green[i] = gflag ? *src++ : 0.0F;
  1151.             blue[i]  = bflag ? *src++ : 0.0F;
  1152.              }
  1153.              alpha[i] = aflag ? *src++ : 1.0F;
  1154.           }
  1155.            }
  1156.            break;
  1157.         default:
  1158.            gl_error( GL_INVALID_ENUM, "glTexImage1/2D(type)" );
  1159.      } /* switch */
  1160.  
  1161.      /* apply scale and/or bias */
  1162.      if (scale_or_bias) {
  1163.         for (i=0;i<width;i++) {
  1164.            register GLfloat r, g, b, a;
  1165.            r = red[i]   * CC.Pixel.RedScale   + CC.Pixel.RedBias;
  1166.            g = green[i] * CC.Pixel.GreenScale + CC.Pixel.GreenBias;
  1167.            b = blue[i]  * CC.Pixel.BlueScale  + CC.Pixel.BlueBias;
  1168.            a = alpha[i] * CC.Pixel.AlphaScale + CC.Pixel.AlphaBias;
  1169.            red[i]   = CLAMP( r, 0.0F, 1.0F );
  1170.            green[i] = CLAMP( g, 0.0F, 1.0F );
  1171.            blue[i]  = CLAMP( b, 0.0F, 1.0F );
  1172.            alpha[i] = CLAMP( a, 0.0F, 1.0F );
  1173.         }
  1174.      }
  1175.  
  1176.      /* save 8-bit components */
  1177.      switch (components) {
  1178.         case 1:  /* red */
  1179.            for (i=0;i<width;i++) {
  1180.           *texptr++ = (GLubyte) (GLint) (red[i] * 255.0F);
  1181.            }
  1182.            break;
  1183.         case 2:  /* red, alpha */
  1184.            for (i=0;i<width;i++) {
  1185.           *texptr++ = (GLubyte) (GLint) (red[i] * 255.0F);
  1186.           *texptr++ = (GLubyte) (GLint) (alpha[i] * 255.0F);
  1187.            }
  1188.            break;
  1189.         case 3:  /* red, green, blue */
  1190.            for (i=0;i<width;i++) {
  1191.           *texptr++ = (GLubyte) (GLint) (red[i] * 255.0F);
  1192.           *texptr++ = (GLubyte) (GLint) (green[i] * 255.0F);
  1193.           *texptr++ = (GLubyte) (GLint) (blue[i] * 255.0F);
  1194.            }
  1195.            break;
  1196.         case 4:  /* red, green, blue, alpha */
  1197.            for (i=0;i<width;i++) {
  1198.           *texptr++ = (GLubyte) (GLint) (red[i] * 255.0F);
  1199.           *texptr++ = (GLubyte) (GLint) (green[i] * 255.0F);
  1200.           *texptr++ = (GLubyte) (GLint) (blue[i] * 255.0F);
  1201.           *texptr++ = (GLubyte) (GLint) (alpha[i] * 255.0F);
  1202.            }
  1203.            break;
  1204.      } /* switch components */
  1205.  
  1206.       } /* general solution */
  1207.  
  1208.    } /* for row */
  1209.  
  1210.    return texture;
  1211. }
  1212.  
  1213.  
  1214. void gl_teximage1d( GLint level, GLint components,
  1215.             GLsizei width, GLint border,
  1216.             const GLubyte *pixels )
  1217. {
  1218.    /* check if we can delete the current image */
  1219.    if (CC.TextureImage1D[level] && CC.TextureImage1DDeleteFlag[level]) {
  1220.       free( CC.TextureImage1D[level] );
  1221.    }
  1222.  
  1223.    CC.TextureComponents1D[level] = components;
  1224.    CC.TextureWidth1D[level] = width + border;
  1225.    CC.TextureBorder1D[level] = border;
  1226.    CC.TextureImage1D[level] = (GLubyte *) pixels;
  1227. }
  1228.  
  1229.  
  1230.  
  1231. void glTexImage1D( GLenum target, GLint level, GLint components,
  1232.            GLsizei width, GLint border, GLenum format,
  1233.            GLenum type, const GLvoid *pixels )
  1234. {
  1235.    GLubyte *texture;
  1236.  
  1237.    if (INSIDE_BEGIN_END) {
  1238.       gl_error( GL_INVALID_OPERATION, "glTexImage1D" );
  1239.       return;
  1240.    }
  1241.    if (target!=GL_TEXTURE_1D) {
  1242.       gl_error( GL_INVALID_ENUM, "glTexImage1D" );
  1243.       return;
  1244.    }
  1245.    if (level<0 || level>=MAX_TEXTURE_LEVELS) {
  1246.       gl_error( GL_INVALID_VALUE, "glTexImage1D(level)" );
  1247.       return;
  1248.    }
  1249.    if (components<0 || components>4) {
  1250.       gl_error( GL_INVALID_VALUE, "glTexImage1D(components)" );
  1251.       return;
  1252.    }
  1253.    if (width<0 || width>2+MAX_TEXTURE_SIZE) {
  1254.       gl_error( GL_INVALID_VALUE, "glTexImage1D(width)" );
  1255.       return;
  1256.    }
  1257.    /* assert( width == 2^k + 2*border for some k);*/
  1258.    if (border!=0 && border!=1) {
  1259.       gl_error( GL_INVALID_VALUE, "glTexImage1D(border)" );
  1260.       return;
  1261.    }
  1262.  
  1263.    /* Convert texture image to GLubytes */
  1264.    texture = unpack_texture( components, width+border, 1,
  1265.                              format, type, pixels );
  1266.    if (!texture) {
  1267.       return;
  1268.    }
  1269.  
  1270.    /* install the texture */
  1271.    if (CC.ExecuteFlag) {
  1272.       gl_teximage1d( level, components, width, border, texture );
  1273.    }
  1274.    if (CC.CompileFlag) {
  1275.       gl_save_teximage1d( level, components, width, border, texture );
  1276.       /* Mark the image as don't delete, it'll get deleted if/when the */
  1277.       /* display list is deallocated. */
  1278.       CC.TextureImage1DDeleteFlag[level] = GL_FALSE;
  1279.    }
  1280.    else {
  1281.       /* Mark this image as deletable because it's not in a display list. */
  1282.       CC.TextureImage1DDeleteFlag[level] = GL_TRUE;
  1283.    }
  1284. }
  1285.  
  1286.  
  1287.  
  1288. void gl_teximage2d( GLint level, GLint components,
  1289.             GLsizei width, GLsizei height, GLint border,
  1290.             const GLubyte *pixels )
  1291. {
  1292.    /* check if we can delete the current image */
  1293.    if (CC.TextureImage2D[level] && CC.TextureImage2DDeleteFlag[level]) {
  1294.       free( CC.TextureImage2D[level] );
  1295.    }
  1296.  
  1297.    CC.TextureComponents2D[level] = components;
  1298.    CC.TextureWidth2D[level] = width + border;
  1299.    CC.TextureHeight2D[level] = height + border;
  1300.    CC.TextureBorder2D[level] = border;
  1301.    CC.TextureImage2D[level] = (GLubyte *) pixels;
  1302. }
  1303.  
  1304.  
  1305.  
  1306. void glTexImage2D( GLenum target, GLint level, GLint components,
  1307.            GLsizei width, GLsizei height, GLint border,
  1308.            GLenum format, GLenum type, const GLvoid *pixels )
  1309. {
  1310.    GLubyte *texture;
  1311.  
  1312.    if (INSIDE_BEGIN_END) {
  1313.       gl_error( GL_INVALID_OPERATION, "glTexImage2D" );
  1314.       return;
  1315.    }
  1316.    if (target!=GL_TEXTURE_2D) {
  1317.       gl_error( GL_INVALID_ENUM, "glTexImage2D(target)" );
  1318.       return;
  1319.    }
  1320.    if (level<0 || level>=MAX_TEXTURE_LEVELS) {
  1321.       gl_error( GL_INVALID_VALUE, "glTexImage2D(level)" );
  1322.       return;
  1323.    }
  1324.    if (components<0 || components>4) {
  1325.       gl_error( GL_INVALID_VALUE, "glTexImage2D(components)" );
  1326.       return;
  1327.    }
  1328.    if (width<0 || width>2+MAX_TEXTURE_SIZE) {
  1329.       gl_error( GL_INVALID_VALUE, "glTexImage2D(width)" );
  1330.       return;
  1331.    }
  1332.    if (height<0 || height>2+MAX_TEXTURE_SIZE) {
  1333.       gl_error( GL_INVALID_VALUE, "glTexImage2D(height)" );
  1334.       return;
  1335.    }
  1336.    /* assert( width == 2^k + 2*border for some k);*/
  1337.    if (border!=0 && border!=1) {
  1338.       gl_error( GL_INVALID_VALUE, "glTexImage2D(border)" );
  1339.       return;
  1340.    }
  1341.  
  1342.    /* Convert texture image to GLubytes */
  1343.    texture = unpack_texture( components, width+border, height+border,
  1344.                              format, type, pixels );
  1345.    if (!texture) {
  1346.       return;
  1347.    }
  1348.  
  1349.    /* install the texture */
  1350.    if (CC.ExecuteFlag) {
  1351.       gl_teximage2d( level, components, width, height, border, texture );
  1352.    }
  1353.    if (CC.CompileFlag) {
  1354.       gl_save_teximage2d( level, components, width, height, border, texture );
  1355.       /* Mark the image as don't delete, it'll get deleted if/when the */
  1356.       /* display list is deallocated. */
  1357.       CC.TextureImage2DDeleteFlag[level] = GL_FALSE;
  1358.    }
  1359.    else {
  1360.       /* Mark this image as deletable because it's not in a display list. */
  1361.       CC.TextureImage2DDeleteFlag[level] = GL_TRUE;
  1362.    }
  1363. }
  1364.  
  1365.  
  1366.  
  1367. void glGetTexImage( GLenum target, GLint level, GLenum format,
  1368.             GLenum type, GLvoid *pixels )
  1369. {
  1370.    /* TODO */
  1371. }
  1372.  
  1373.  
  1374.  
  1375.  
  1376. /**********************************************************************/
  1377. /*                   Perform Texture Mapping                          */
  1378. /**********************************************************************/
  1379.  
  1380.  
  1381.  
  1382. /*
  1383.  * Combine incoming fragment color with texel color to produce output color.
  1384.  */
  1385. static void apply_texture( GLuint n, GLint components,
  1386.      GLubyte red[], GLubyte green[], GLubyte blue[], GLubyte alpha[],
  1387.      GLubyte tred[], GLubyte tgreen[], GLubyte tblue[], GLubyte talpha[] )
  1388. {
  1389.    register GLuint i;
  1390.    GLint envred, envgreen, envblue;
  1391.  
  1392.    /* Texture environment color */
  1393.    envred   = (GLint) (CC.Texture.EnvColor[0] * 255.0F);
  1394.    envgreen = (GLint) (CC.Texture.EnvColor[1] * 255.0F);
  1395.    envblue  = (GLint) (CC.Texture.EnvColor[2] * 255.0F);
  1396.  
  1397.    if (CC.RedScale!=255.0) {
  1398.       /* This is a hack!  Rescale input colors from [0,scale] to [0,255]. */
  1399.       GLfloat rscale = 255.0 / CC.RedScale;
  1400.       GLfloat gscale = 255.0 / CC.GreenScale;
  1401.       GLfloat bscale = 255.0 / CC.BlueScale;
  1402.       GLfloat ascale = 255.0 / CC.AlphaScale;
  1403.       for (i=0;i<n;i++) {
  1404.      red[i]   = (GLint) (red[i]   * rscale);
  1405.      green[i] = (GLint) (green[i] * gscale);
  1406.      blue[i]  = (GLint) (blue[i]  * bscale);
  1407.      alpha[i] = (GLint) (alpha[i] * ascale);
  1408.       }
  1409.    }
  1410.  
  1411. /*
  1412.  * Use (A*(B+1)) >> 8 as a fast approximation of (A*B)/255 for A and B in [0,255]
  1413.  */
  1414. #define PROD(A,B)   (((GLint)(A) * (GLint)(B)+1) >> 8)
  1415.  
  1416.    switch (CC.Texture.EnvMode) {
  1417.       case GL_MODULATE:
  1418.          switch (components) {
  1419.         case 1:  /* luminance */
  1420.            for (i=0;i<n;i++) {
  1421.           /* Cv = LtCf */
  1422.           red[i]   = PROD( tred[i], red[i] );
  1423.           green[i] = PROD( tred[i], green[i] );
  1424.           blue[i]  = PROD( tred[i], blue[i] );
  1425.           /* Av = Af */
  1426.            }
  1427.            break;
  1428.         case 2: /* luminance, alpha */
  1429.            for (i=0;i<n;i++) {
  1430.           /* Cv = LtCf */
  1431.           red[i]   = PROD( tred[i], red[i] );
  1432.           green[i] = PROD( tred[i], green[i] );
  1433.           blue[i]  = PROD( tred[i], blue[i] );
  1434.           /* Av = AtAf */
  1435.           alpha[i] = PROD( talpha[i], alpha[i] );
  1436.            }
  1437.            break;
  1438.         case 3: /* rgb */
  1439.            for (i=0;i<n;i++) {
  1440.           /* Cv = CtCf */
  1441.           red[i]   = PROD( tred[i],   red[i] );
  1442.           green[i] = PROD( tgreen[i], green[i] );
  1443.           blue[i]  = PROD( tblue[i],  blue[i] );
  1444.           /* Av = Af */
  1445.            }
  1446.            break;
  1447.         case 4: /* rgb, alpha */
  1448.            for (i=0;i<n;i++) {
  1449.           /* Cv = CtCf */
  1450.           red[i]   = PROD( tred[i],   red[i] );
  1451.           green[i] = PROD( tgreen[i], green[i] );
  1452.           blue[i]  = PROD( tblue[i],  blue[i] );
  1453.           /* Av = AtAf */
  1454.           alpha[i] = PROD( talpha[i], alpha[i] );
  1455.            }
  1456.            break;
  1457.      } /* components */
  1458.      break;
  1459.       case GL_DECAL:
  1460.          switch (components) {
  1461.         case 3:
  1462.            for (i=0;i<n;i++) {
  1463.           /* Cv = Ct */
  1464.           red[i]   = tred[i];
  1465.           green[i] = tgreen[i];
  1466.           blue[i]  = tblue[i];
  1467.           /* Av = Af */
  1468.            }
  1469.            break;
  1470.         case 4:
  1471.            for (i=0;i<n;i++) {
  1472.           /* Cv = (1-At)Cf + AtCt */
  1473.           GLint t = talpha[i], s = 255 - t;
  1474.           red[i]   = PROD(s,red[i])   + PROD(t,tred[i]);
  1475.           green[i] = PROD(s,green[i]) + PROD(t,tgreen[i]);
  1476.           blue[i]  = PROD(s,blue[i])  + PROD(t,tblue[i]);
  1477.           /* Av = Af */
  1478.            }
  1479.            break;
  1480.      }
  1481.      break;
  1482.       case GL_BLEND:
  1483.      switch (components) {
  1484.         case 1:
  1485.            for (i=0;i<n;i++) {
  1486.           /* Cv = (1-Lt)Cf + LtCc */
  1487.           GLint t = tred[i], s = 255 - t;
  1488.           red[i]   = PROD(s,red[i])   + PROD(t,envred);
  1489.           green[i] = PROD(s,green[i]) + PROD(t,envgreen);
  1490.           blue[i]  = PROD(s,blue[i])  + PROD(t,envblue);
  1491.           /* Av = Af */
  1492.            }
  1493.            break;
  1494.         case 2:
  1495.            for (i=0;i<n;i++) {
  1496.           /* Cv = (1-Lt)Cf + LtCc */
  1497.           GLint t = tred[i], s = 255 - t;
  1498.           red[i]   = PROD(s,red[i])   + PROD(t,envred);
  1499.           green[i] = PROD(s,green[i]) + PROD(t,envgreen);
  1500.           blue[i]  = PROD(s,blue[i])  + PROD(t,envblue);
  1501.           /* Av = AtAf */
  1502.           alpha[i] = PROD(talpha[i], alpha[i]);
  1503.            }
  1504.            break;
  1505.         case 3:
  1506.            for (i=0;i<n;i++) {
  1507.           /* Cv = (1-Ct)Cf + CtCc */
  1508.           red[i]   = PROD((255-tred[i]),  red[i]  ) + PROD(tred[i],  envred  );
  1509.           green[i] = PROD((255-tgreen[i]),green[i]) + PROD(tgreen[i],envgreen);
  1510.           blue[i]  = PROD((255-tblue[i]), blue[i] ) + PROD(tblue[i], envblue );
  1511.           /* Av = Af */
  1512.            }
  1513.            break;
  1514.         case 4:
  1515.            for (i=0;i<n;i++) {
  1516.           /* Cv = (1-Ct)Cf + CtCc */
  1517.           red[i]   = PROD((255-tred[i]),  red[i]  ) + PROD(tred[i],  envred  );
  1518.           green[i] = PROD((255-tgreen[i]),green[i]) + PROD(tgreen[i],envgreen);
  1519.           blue[i]  = PROD((255-tblue[i]), blue[i] ) + PROD(tblue[i], envblue );
  1520.           /* Av = AtAf */
  1521.           alpha[i] = PROD(talpha[i], alpha[i]);
  1522.            }
  1523.            break;
  1524.      }
  1525.      break;
  1526.       case GL_REPLACE_EXT:
  1527.      switch (components) {
  1528.         case 1:
  1529.            for (i=0;i<n;i++) {
  1530.           /* Cv = Lt */
  1531.           red[i] = green[i] = blue[i] = tred[i];
  1532.           /* Av = Af */
  1533.            }
  1534.            break;
  1535.         case 2:
  1536.            for (i=0;i<n;i++) {
  1537.           /* Cv = Lt */
  1538.           red[i] = green[i] = blue[i] = tred[i];
  1539.           /* Av = At */
  1540.           alpha[i] = talpha[i];
  1541.            }
  1542.            break;
  1543.         case 3:
  1544.            for (i=0;i<n;i++) {
  1545.           /* Cv = Ct */
  1546.           red[i]   = tred[i];
  1547.           green[i] = tgreen[i];
  1548.           blue[i]  = tblue[i];
  1549.           /* Av = Af */
  1550.            }
  1551.            break;
  1552.         case 4:
  1553.            for (i=0;i<n;i++) {
  1554.           /* Cv = Ct */
  1555.           red[i]   = tred[i];
  1556.           green[i] = tgreen[i];
  1557.           blue[i]  = tblue[i];
  1558.           /* Av = At */
  1559.           alpha[i] = talpha[i];
  1560.            }
  1561.            break;
  1562.      }
  1563.      break;
  1564.    }
  1565. #undef PROD
  1566.  
  1567.    if (CC.RedScale!=255.0) {
  1568.       /* This is a hack!  Rescale input colors from [0,255] to [0,scale]. */
  1569.       GLfloat rscale = CC.RedScale   / 255.0;
  1570.       GLfloat gscale = CC.GreenScale / 255.0;
  1571.       GLfloat bscale = CC.BlueScale  / 255.0;
  1572.       GLfloat ascale = CC.AlphaScale / 255.0;
  1573.       for (i=0;i<n;i++) {
  1574.      red[i]   = (GLint) (red[i]   * rscale);
  1575.      green[i] = (GLint) (green[i] * gscale);
  1576.      blue[i]  = (GLint) (blue[i]  * bscale);
  1577.      alpha[i] = (GLint) (alpha[i] * ascale);
  1578.       }
  1579.    }
  1580.  
  1581.  
  1582. }
  1583.  
  1584.  
  1585. /*
  1586.  * Apply the 1-D texture to an array of pixels.
  1587.  */
  1588. void gl_texture_pixels_1d( GLuint n, GLfloat s[], 
  1589.                GLubyte red[], GLubyte green[],
  1590.                GLubyte blue[], GLubyte alpha[] )
  1591. {
  1592.    GLubyte tred[PB_SIZE], tgreen[PB_SIZE];
  1593.    GLubyte tblue[PB_SIZE], talpha[PB_SIZE];
  1594.    GLint alpha_offset;
  1595.    GLuint level;
  1596.    GLuint i;
  1597.  
  1598.    level = 0;
  1599.  
  1600.    if (!CC.TextureImage1D[level]) {
  1601.       /* no texture image */
  1602.       return;
  1603.    }
  1604.  
  1605.    /* alpha_offset = offset of the alpha value in the texel of a texture image */
  1606.    if (CC.TextureComponents1D[level]==2) {
  1607.       alpha_offset = 1;
  1608.    }
  1609.    else if (CC.TextureComponents1D[level]==4) {
  1610.       alpha_offset = 3;
  1611.    }
  1612.    else {
  1613.       alpha_offset = 0;
  1614.    }
  1615.  
  1616.    /*
  1617.     * Compute texel colors.
  1618.     */
  1619.    for (i=0;i<n;i++) {
  1620.       GLfloat ss;
  1621.       GLboolean border;
  1622.  
  1623.       border = GL_FALSE;   /* Use border pixel color? */
  1624.  
  1625.       /* S COORDINATE */
  1626.       if (CC.Texture.WrapS1D==GL_REPEAT) {
  1627.          ss = s[i];
  1628.          while (ss<0.0F)  ss += 1.0F;
  1629.          while (ss>1.0F)  ss -= 1.0F;
  1630. /*     ss = s[i] - (GLfloat) (GLint) s[i];*/
  1631.       }
  1632.       else {
  1633.      /* GL_CLAMP */
  1634.      if (s[i]<0.0F || s[i]>1.0F) {
  1635.         if (CC.TextureBorder1D[level]) {
  1636.            /* use border texel */
  1637.            border = GL_TRUE;
  1638.         }
  1639.         else {
  1640.            /* use border color */
  1641.            ss = (s[i]<0.0F) ? 0.0F : 1.0F;
  1642.         }
  1643.      }
  1644.      else {
  1645.         ss = s[i];
  1646.      }
  1647.       }
  1648.  
  1649.       if (border) {
  1650.      tred[i]   = (GLint) (CC.Texture.BorderColor[0] * 255.0F);
  1651.      tgreen[i] = (GLint) (CC.Texture.BorderColor[1] * 255.0F);
  1652.      tblue[i]  = (GLint) (CC.Texture.BorderColor[2] * 255.0F);
  1653.      talpha[i] = (GLint) (CC.Texture.BorderColor[3] * 255.0F);
  1654.       }
  1655.       else {
  1656.      GLuint x, p;
  1657.      if (ss<1.0F) {
  1658.         x = (GLuint) (CC.TextureWidth1D[level] * ss);
  1659.      }
  1660.      else {
  1661.         x = CC.TextureWidth1D[level]-1;
  1662.      }
  1663.  
  1664.      p = CC.TextureComponents1D[level] * x;
  1665.      tred[i]   = CC.TextureImage1D[level][p];
  1666.      tgreen[i] = CC.TextureImage1D[level][p+1];
  1667.      tblue[i]  = CC.TextureImage1D[level][p+2];
  1668.      talpha[i] = CC.TextureImage1D[level][p+alpha_offset];
  1669.       }
  1670.    }
  1671.  
  1672.    apply_texture( n, CC.TextureComponents1D[level],
  1673.           red, green, blue, alpha, tred, tgreen, tblue, talpha );
  1674. }
  1675.  
  1676.  
  1677.  
  1678. /*
  1679.  * Apply the 2-D texture to an array of pixels.
  1680.  */
  1681. void gl_texture_pixels_2d( GLuint n,
  1682.                GLfloat s[], GLfloat t[],
  1683.                GLubyte red[], GLubyte green[],
  1684.                GLubyte blue[], GLubyte alpha[] )
  1685. {
  1686.    GLubyte tred[PB_SIZE], tgreen[PB_SIZE];
  1687.    GLubyte tblue[PB_SIZE], talpha[PB_SIZE];
  1688.    GLint alpha_offset;
  1689.    GLuint level;
  1690.    GLuint i;
  1691.  
  1692.    level = 0;
  1693.  
  1694.    if (!CC.TextureImage2D[level]) {
  1695.       /* no texture image */
  1696.       return;
  1697.    }
  1698.  
  1699.    /* alpha_offset = offset of the alpha value in the texel of a texture image */
  1700.    if (CC.TextureComponents2D[level]==2) {
  1701.       alpha_offset = 1;
  1702.    }
  1703.    else if (CC.TextureComponents2D[level]==4) {
  1704.       alpha_offset = 3;
  1705.    }
  1706.    else {
  1707.       alpha_offset = 0;
  1708.    }
  1709.  
  1710.    /*
  1711.     * Compute texel colors.
  1712.     */
  1713.    for (i=0;i<n;i++) {
  1714.       GLfloat ss, tt;
  1715.       GLboolean border;
  1716.  
  1717.       border = GL_FALSE;   /* Use border pixel color? */
  1718.  
  1719.       /* S COORDINATE */
  1720.       if (CC.Texture.WrapS2D==GL_REPEAT) {
  1721.          ss = s[i];
  1722.          while (ss<0.0F)  ss += 1.0F;
  1723.          while (ss>1.0F)  ss -= 1.0F;
  1724. /*         ss = s[i] - (GLfloat) (GLint) s[i];*/
  1725.       }
  1726.       else {
  1727.      /* GL_CLAMP */
  1728.      if (s[i]<0.0F || s[i]>1.0F) {
  1729.         if (CC.TextureBorder2D[level]) {
  1730.            /* use border texel */
  1731.            border = GL_TRUE;
  1732.         }
  1733.         else {
  1734.            /* use border color */
  1735.            ss = (s[i]<0.0F) ? 0.0F : 1.0F;
  1736.         }
  1737.      }
  1738.      else {
  1739.         ss = s[i];
  1740.      }
  1741.       }
  1742.  
  1743.       /* T COORDINATE */
  1744.       if (CC.Texture.WrapT2D==GL_REPEAT) {
  1745.          tt = t[i];
  1746.          while (tt<0.0F)  tt += 1.0F;
  1747.          while (tt>1.0F)  tt -= 1.0F;
  1748. /*         tt = t[i] - (GLfloat) (GLint) t[i];*/
  1749.       }
  1750.       else {
  1751.      /* GL_CLAMP */
  1752.      if (t[i]<0.0F || t[i]>1.0F) {
  1753.         if (CC.TextureBorder2D[level]) {
  1754.            /* use border texel */
  1755.            border = GL_TRUE;
  1756.         }
  1757.         else {
  1758.            /* use border color */
  1759.            tt = (t[i]<0.0F) ? 0.0F : 1.0F;
  1760.         }
  1761.      }
  1762.      else {
  1763.         tt = t[i];
  1764.      }
  1765.       }
  1766.  
  1767.       if (border) {
  1768.      tred[i]   = (GLint) (CC.Texture.BorderColor[0] * 255.0F);
  1769.      tgreen[i] = (GLint) (CC.Texture.BorderColor[1] * 255.0F);
  1770.      tblue[i]  = (GLint) (CC.Texture.BorderColor[2] * 255.0F);
  1771.      talpha[i] = (GLint) (CC.Texture.BorderColor[3] * 255.0F);
  1772.       }
  1773.       else {
  1774.      GLuint x, y, p;
  1775.      if (ss<1.0F) {
  1776.         x = (GLuint) (CC.TextureWidth2D[level] * ss);
  1777.      }
  1778.      else {
  1779.         x = CC.TextureWidth2D[level]-1;
  1780.      }
  1781.      if (tt<1.0F) {
  1782.         y = (GLuint) (CC.TextureHeight2D[level] * tt);
  1783.      }
  1784.      else {
  1785.         y = CC.TextureHeight2D[level]-1;
  1786.      }      
  1787.  
  1788.      p = CC.TextureComponents2D[level] * (CC.TextureWidth2D[level] * y + x);
  1789.      tred[i]   = CC.TextureImage2D[level][p];
  1790.      tgreen[i] = CC.TextureImage2D[level][p+1];
  1791.      tblue[i]  = CC.TextureImage2D[level][p+2];
  1792.      talpha[i] = CC.TextureImage2D[level][p+alpha_offset];
  1793.       }
  1794.    }
  1795.  
  1796.    apply_texture( n, CC.TextureComponents2D[level],
  1797.           red, green, blue, alpha, tred, tgreen, tblue, talpha );
  1798. }
  1799.  
  1800.